<template>
  <div class="video-upload-page">
    <div class="page-header">
      <h2>视频上传</h2>
      <p class="tip">支持 MP4、WebM、MOV 格式，单个文件不超过 200MB</p>
    </div>

    <div class="upload-container">
      <!-- 上传区域 -->
      <div class="upload-area" :class="{ 'uploading': isUploading }">
        <!-- 未上传时的提示 -->
        <div class="upload-placeholder" v-if="!selectedVideo && !isUploading">
          <i class="el-icon-video-camera"></i>
          <p>点击或拖拽视频文件到此处</p>
          <label class="select-btn">
            <input
              type="file"
              ref="fileInput"
              accept="video/mp4,video/webm,video/quicktime"
              @change="handleFileSelect"
            >
            选择视频
          </label>
        </div>

        <!-- 已选择视频信息 -->
        <div class="video-info" v-if="selectedVideo && !isUploading">
          <div class="video-preview">
            <video
              :src="selectedVideo.url"
              controls
              class="preview-video"
              @error="handleVideoError"
            ></video>
          </div>
          <div class="video-meta">
            <h4 class="video-name">{{ selectedVideo.name }}</h4>
            <p>格式：{{ getFileExtension(selectedVideo.name) }}</p>
            <p>大小：{{ formatFileSize(selectedVideo.size) }}</p>
            <p>时长：{{ formatDuration(selectedVideo.duration) }}</p>
            <div class="action-btns">
              <el-button
                type="primary"
                @click="startUpload"
                :disabled="!canUpload"
              >
                开始上传
              </el-button>
              <el-button
                type="text"
                @click="clearSelection"
                style="color: #f56c6c;"
              >
                重新选择
              </el-button>
            </div>
          </div>
        </div>

        <!-- 上传中状态 -->
        <div class="uploading-status" v-if="isUploading">
          <el-progress
            :percentage="uploadProgress"
            stroke-width="6"
          ></el-progress>
          <p class="progress-text">
            正在上传：{{ selectedVideo.name }}（{{ uploadProgress }}%）
          </p>
          <el-button
            type="text"
            @click="cancelUpload"
            style="margin-top: 10px;"
          >
            取消上传
          </el-button>
        </div>
      </div>

      <!-- 上传结果提示 -->
      <el-alert
        v-if="uploadSuccess"
        title="上传成功！"
        type="success"
        show-icon
        :closable="true"
        @close="resetUploadStatus"
      ></el-alert>
      <el-alert
        v-if="uploadError"
        :title="`上传失败：${errorMsg}`"
        type="error"
        show-icon
        :closable="true"
        @close="resetUploadStatus"
      ></el-alert>
    </div>

    <!-- 已上传视频列表 -->
    <div class="uploaded-list" v-if="uploadedVideos.length > 0">
      <h3>已上传视频</h3>
      <el-table :data="uploadedVideos" border>
        <el-table-column prop="name" label="视频名称" width="300"></el-table-column>
        <el-table-column label="预览" width="200">
          <template #default="scope">
            <video
              :src="scope.row.url"
              controls
              class="table-video"
            ></video>
          </template>
        </el-table-column>
        <el-table-column prop="size" label="大小"></el-table-column>
        <el-table-column prop="duration" label="时长"></el-table-column>
        <el-table-column prop="uploadTime" label="上传时间"></el-table-column>
        <el-table-column label="操作">
          <template #default="scope">
            <el-button
              type="text"
              @click="handleVideoPlay(scope.row.url)"
            >
              播放
            </el-button>
            <el-button
              type="text"
              style="color: #f56c6c;"
              @click="handleDelete(scope.$index)"
            >
              删除
            </el-button>
          </template>
        </el-table-column>
      </el-table>
    </div>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      // 选中的视频信息
      selectedVideo: null,
      // 上传状态
      isUploading: false,
      uploadProgress: 0,
      uploadSuccess: false,
      uploadError: false,
      errorMsg: '',
      // 已上传视频列表
      uploadedVideos: [],
      // 上传请求取消令牌
      cancelToken: null
    };
  },
  computed: {
    // 判断是否可以上传（视频有效且未超过大小限制）
    canUpload() {
      if (!this.selectedVideo) return false;
      // 限制 200MB
      const maxSize = 200 * 1024 * 1024;
      return this.selectedVideo.size <= maxSize;
    }
  },
  methods: {
    // 处理文件选择
    handleFileSelect(e) {
      const file = e.target.files[0];
      if (!file) return;

      // 验证文件类型
      const validTypes = ['video/mp4', 'video/webm', 'video/quicktime'];
      if (!validTypes.includes(file.type)) {
        this.$message.error('请选择 MP4、WebM 或 MOV 格式的视频');
        this.clearSelection();
        return;
      }

      // 创建视频预览 URL
      const videoUrl = URL.createObjectURL(file);

      // 获取视频时长
      const video = document.createElement('video');
      video.preload = 'metadata';
      video.src = videoUrl;

      video.onloadedmetadata = () => {
        URL.revokeObjectURL(video.src); // 释放临时 URL
        this.selectedVideo = {
          name: file.name,
          size: file.size,
          type: file.type,
          url: videoUrl,
          duration: video.duration, // 时长（秒）
          raw: file
        };
      };

      video.onerror = () => {
        this.$message.error('视频文件损坏，无法预览');
        this.clearSelection();
      };

      // 清空 input 值，允许重复选择同一文件
      this.$refs.fileInput.value = '';
    },

    // 开始上传
    startUpload() {
      if (!this.selectedVideo) return;

      const formData = new FormData();
      formData.append('videoFile', this.selectedVideo.raw); // 与后端参数名一致

      // 创建取消令牌
      const source = axios.CancelToken.source();
      this.cancelToken = source;

      this.isUploading = true;
      this.uploadProgress = 0;

      axios.post('/api/upload/video', formData, {
        cancelToken: source.token,
        onUploadProgress: (progressEvent) => {
          // 计算上传进度（百分比）
          const percent = Math.round(
            (progressEvent.loaded / progressEvent.total) * 100
          );
          this.uploadProgress = percent;
        }
      }).then(response => {
        if (response.data.code === 200) {
          // 上传成功，添加到已上传列表
          this.uploadedVideos.unshift({
            id: response.data.data.videoId,
            name: this.selectedVideo.name,
            url: response.data.data.videoUrl, // 后端返回的视频访问地址
            size: this.formatFileSize(this.selectedVideo.size),
            duration: this.formatDuration(this.selectedVideo.duration),
            uploadTime: new Date().toLocaleString()
          });
          this.uploadSuccess = true;
          this.clearSelection();
        } else {
          this.uploadError = true;
          this.errorMsg = response.data.msg || '上传失败，请重试';
        }
      }).catch(error => {
        if (!axios.isCancel(error)) {
          this.uploadError = true;
          this.errorMsg = error.message || '网络异常，上传中断';
        }
      }).finally(() => {
        this.isUploading = false;
        this.cancelToken = null;
      });
    },

    // 取消上传
    cancelUpload() {
      if (this.cancelToken) {
        this.cancelToken.cancel('用户取消上传');
      }
      this.isUploading = false;
      this.uploadProgress = 0;
      this.cancelToken = null;
    },

    // 清除选中的视频
    clearSelection() {
      if (this.selectedVideo?.url) {
        URL.revokeObjectURL(this.selectedVideo.url); // 释放 URL 对象
      }
      this.selectedVideo = null;
      this.$refs.fileInput.value = '';
    },

    // 重置上传状态提示
    resetUploadStatus() {
      this.uploadSuccess = false;
      this.uploadError = false;
      this.errorMsg = '';
    },

    // 处理视频播放（新窗口打开）
    handleVideoPlay(url) {
      window.open(url, '_blank');
    },

    // 删除已上传视频
    handleDelete(index) {
      this.$confirm('确定要删除该视频吗？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        const videoId = this.uploadedVideos[index].id;
        // 调用后端删除接口
        axios.delete(`/api/video/${videoId}`).then(() => {
          this.uploadedVideos.splice(index, 1);
          this.$message.success('删除成功');
        }).catch(() => {
          this.$message.error('删除失败');
        });
      }).catch(() => {});
    },

    // 辅助函数：获取文件扩展名
    getFileExtension(filename) {
      return filename.split('.').pop().toUpperCase();
    },

    // 辅助函数：格式化文件大小（B → MB）
    formatFileSize(size) {
      if (size < 1024) return `${size} B`;
      if (size < 1024 * 1024) return `${(size / 1024).toFixed(1)} KB`;
      return `${(size / (1024 * 1024)).toFixed(1)} MB`;
    },

    // 辅助函数：格式化视频时长（秒 → 分:秒）
    formatDuration(seconds) {
      if (isNaN(seconds)) return '未知';
      const mins = Math.floor(seconds / 60);
      const secs = Math.floor(seconds % 60);
      return `${mins}:${secs.toString().padStart(2, '0')}`;
    },

    // 处理视频预览错误
    handleVideoError() {
      this.$message.warning('视频预览失败，可能是格式不支持');
    }
  },
  beforeDestroy() {
    // 组件销毁时释放 URL 对象
    if (this.selectedVideo?.url) {
      URL.revokeObjectURL(this.selectedVideo.url);
    }
    // 取消正在进行的上传
    if (this.cancelToken) {
      this.cancelToken.cancel('组件销毁，上传取消');
    }
  }
};
</script>

<style scoped>
.video-upload-page {
  max-width: 1200px;
  margin: 0 auto;
  padding: 20px;
}

.page-header {
  margin-bottom: 30px;
}

.page-header h2 {
  margin: 0 0 10px 0;
  color: #333;
}

.tip {
  margin: 0;
  color: #666;
  font-size: 14px;
}

.upload-container {
  background: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
  padding: 20px;
  margin-bottom: 30px;
}

.upload-area {
  border: 2px dashed #ddd;
  border-radius: 6px;
  padding: 30px;
  transition: all 0.3s;
}

.upload-area.uploading {
  border-style: solid;
  border-color: #409eff;
}

.upload-placeholder {
  text-align: center;
  padding: 40px 0;
}

.upload-placeholder i {
  font-size: 48px;
  color: #409eff;
  margin-bottom: 15px;
}

.upload-placeholder p {
  color: #666;
  margin-bottom: 20px;
}

.select-btn {
  display: inline-block;
  padding: 8px 16px;
  background: #409eff;
  color: #fff;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  transition: background 0.2s;
}

.select-btn:hover {
  background: #66b1ff;
}

.select-btn input {
  display: none;
}

.video-info {
  display: flex;
  gap: 20px;
}

.video-preview {
  flex: 0 0 320px;
}

.preview-video {
  width: 100%;
  border-radius: 4px;
  background: #000;
}

.video-meta {
  flex: 1;
  min-width: 0;
}

.video-name {
  margin: 0 0 15px 0;
  font-size: 16px;
  color: #333;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.video-meta p {
  margin: 8px 0;
  color: #666;
  font-size: 14px;
}

.action-btns {
  margin-top: 20px;
}

.uploading-status {
  text-align: center;
  padding: 40px 20px;
}

.progress-text {
  margin: 15px 0 0 0;
  color: #666;
}

.uploaded-list {
  background: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
  padding: 20px;
}

.uploaded-list h3 {
  margin: 0 0 15px 0;
  color: #333;
  font-size: 16px;
}

.table-video {
  width: 100%;
  height: 80px;
  object-fit: cover;
  border-radius: 4px;
}

/* 响应式调整 */
@media (max-width: 768px) {
  .video-info {
    flex-direction: column;
  }

  .video-preview {
    flex: none;
    width: 100%;
  }
}
</style>
